from os.path import dirname, isfile, join as joinfile, realpath
from time import sleep
from os import environ, listdir, popen, system
from functools import partial
from datetime import time
from threading import Thread

from PyQt5.QtWidgets import (QMainWindow, QMessageBox as QMessage,
                             QSystemTrayIcon)
from PyQt5.QtCore import Qt, QTimer, QUrl
from QLed import QLed
from validators import url as check_url
from pyperclip import copy

from .design import Ui_MainWindow
from .combobox import ExtendedComboBox
from .doing_data import DoingWithData
from .geometry import SetGeometry
from .cache import CacheData
from .current import CurrentEdit
from .view import ViewData
from .mode import ModeData
from .history import ExportData
from .notify import Notify
from .dock import DockWidget
from .track import TrackData
from .parse_anime import ParseAnime
from .parse_manga import ParseManga
from .parse_ranobe import ParseRanobe
from .download import AnimeDownload
from .funcs import checkVoice, seticon, networkConnected


class GlobalParser(QMainWindow):
    def __init__(self):
        super(GlobalParser, self).__init__()
        self.data = DoingWithData('setting')
        self.location = SetGeometry()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.view = ViewData()
        self.mode = ModeData()
        self.now = CurrentEdit()
        self.notification = Notify()
        self.manga = ParseManga()
        self.anime = ParseAnime()
        self.ranobe = ParseRanobe()
        self.load = AnimeDownload()
        self.track = TrackData()
        self.cached = CacheData()
        self.export = ExportData()

        geo = self.data.get()['geometry']
        cmd = 'ps -ax | grep -v grep | grep chromedriver'

        self.setWindowFlag(Qt.FramelessWindowHint)
        [i(*geo[2:]) for i in (self.setMinimumSize, self.setMaximumSize)]
        self.setGeometry(*geo)

        self.error_connect = self.global_mode = False
        self.queue_change = self.tracking_start = False
        self.queue, self.queue_s, self.queue_d = [], False, True
        self.click = self.enable = self.tab = self.opened = 0
        self.suffix, self.values = False, (0, 9999999, 0, 9999999)
        self.path, self.tray_set = dirname(realpath(__file__)), ''
        self.down = f'{environ["HOME"]}/.cache/anima/downloads'
        self.funcs = (self.anime, self.manga, self.ranobe, self.load)
        self.chrome, self.track_list = lambda: popen(cmd, 'r'), False
        self.cache = self.cached.read(f'{environ["HOME"]}/.cache/anima')
        self.notify = self.data.get()['notify']['notify']
        self.update_index = (self.sourceChanged, self.load.changed)
        self.local_index = {0: 0, 1: 0, 2: 0, 'start': 1}

        self.combobox = ExtendedComboBox(self)
        self.combobox.setGeometry(101, 6, 257, 25)

        self.docked = (self.ui.dockWidget, self.ui.dockWidget_2,
            self.ui.dockWidget_3, self.ui.dockWidget_4, self.ui.dockWidget_5,
            self.ui.dockWidget_6, self.ui.dockWidget_7, self.ui.dockWidget_8)

        self.dock = [DockWidget(i) for i in self.docked]
        self.tool = (self.ui.toolButton, self.ui.toolButton_2,
            self.ui.toolButton_3, self.ui.toolButton_4, self.ui.toolButton_5,
            self.ui.toolButton_6, self.ui.toolButton_7, self.ui.toolButton_8,
            self.ui.toolButton_9, self.ui.toolButton_10, self.ui.toolButton_11,
            self.ui.toolButton_12, self.ui.toolButton_13,
            self.ui.toolButton_14, self.ui.toolButton_15,
            self.ui.toolButton_16, self.ui.toolButton_17,
            self.ui.toolButton_18, self.ui.toolButton_21,
            self.ui.toolButton_22, self.ui.toolButton_23)
        self.combo = (self.ui.comboBox, self.combobox, self.ui.comboBox_3,
            self.ui.comboBox_4, self.ui.comboBox_5, self.ui.comboBox_6,
            self.ui.comboBox_7, self.ui.comboBox_8, self.ui.comboBox_9,
            self.ui.comboBox_10, self.ui.comboBox_11, self.ui.comboBox_2)
        self.lcd = (self.ui.lcdNumber, self.ui.lcdNumber_2)
        self.spin = (self.ui.spinBox, self.ui.spinBox_2, self.ui.timeEdit)
        self.line = (self.ui.lineEdit, self.ui.textEdit, self.ui.textEdit_2,
            self.ui.listWidget, self.ui.listWidget_2, self.ui.lineEdit_2)
        self.bar = (self.ui.progressBar, self.ui.progressBar_2,
                    self.ui.progressBar_3, self.ui.dial)
        self.box = (self.ui.groupBox, self.ui.groupBox_2, self.ui.groupBox_3,
            self.ui.groupBox_4, self.ui.webEngineView)
        self.push = (self.ui.pushButton, self.ui.pushButton_2)

        self.box[4].urlChanged.connect(self.setWebUrl)
        self.bar[2].valueChanged.connect(self.changeProgress)
        self.spin[2].timeChanged.connect(self.setNewRange)
        self.spin[0].valueChanged.connect(self.sourceClear)

        funcs = (self.editLoadPercent, self.tracked)
        start = (self.defaultIcons, self.checkGeometry, self.showCheckWebSite,
                 self.changeMode, self.tracked, self.changeHistory,
                 self.listChangeSheme)
        colors = ('#8BC6EC', '#00e916', '#2fe490')
        ctime = (int(self.cache[9]) if self.cache else 15) * 60 * 1000

        mode = {
            0: self.changeMode, 3: self.changeColorSheme, 4: self.setGeoApp,
            5: self.changeHistory, 11: self.showView
        }
        click = {
            0: self.closed, 1: self.sourceWeb, 2: self.choiseNotify,
            3: self.sourceSeries, 4: partial(self.choiseValue, 0),
            5: partial(self.choiseValue, 1), 6: self.sourceDelete,
            7: self.dock[4].opening, 8: self.dock[0].opening,
            9: self.stoped, 10: self.dock[1].opening,
            11: self.sourceLog, 12: self.choiseMode, 13: self.clickExport,
            14: self.sourceDownloading, 15: self.sourcePlayer,
            16: partial(self.checkItems, 1), 17: partial(self.checkItems, 0),
            18: self.loadUrl, 19: self.copyCurrentLink, 20: self.openView
        }
        push = {0: self.dockStop, 1: self.dock[7].close}

        self.tray = QSystemTrayIcon(self)
        self.tray.activated.connect(self.trayExecute)
        self.tray.setIcon(seticon('track'))
        self.tray.show()

        self.led = QLed(self, shape=QLed.Circle)
        self.led.setGeometry(370, 195, 14, 14)

        self.timer = [QTimer() for _ in range(2)]
        [v.timeout.connect(funcs[i]) for i, v in enumerate(self.timer)]
        [v.start((1000, ctime)[i]) for i, v in enumerate(self.timer)]

        [i() for i in start]

        self.spin[2].setTime(time(0, ctime // 60 // 1000, 0))

        [self.combo[i].currentIndexChanged.connect(mode[i]) for i in range(12)
                                            if i not in (1, 2, 6, 7, 8, 9, 10)]
        self.combo[1].activated.connect(self.sourceChanged)
        self.line[4].itemDoubleClicked.connect(self.openNotify)
        self.bar[3].valueChanged.connect(self.changeZoom)
        # self.line[4].itemEntered.connect(self.openNotify)

        [v.clicked.connect(click[i]) for i, v in enumerate(self.tool)]
        [v.clicked.connect(push[i]) for i, v in enumerate(self.push)]
        self.ui.toolButton_19.clicked.connect(self.dock[6].opening)

        for i, v in enumerate(colors):
            self.bar[i].setStyleSheet(f'selection-background-color: {v};')

        self.cashing = {
            0: lambda e, l: [i() for i in l if e],
            1: self.bar[0].setValue,
            2: self.bar[1].setValue,
            5: self.tool[2].setIcon
        }

        self.bar[3].setValue(70)
        self.changeZoom(70)
        self.view.about(self.data.get(), self.line[2])

    def keyPressEvent(self, QKeyEvent):
        """ Hide application at press key <Esc>. """
        self.hidded() if QKeyEvent.key() == 16777216 else None

    def hidded(self):
        self.hide()
        self.click += 1
        tuple((i.hide() for i in self.dock))

    def defaultIcons(self):
        icon = ('close', 'web', self.cache[5] if self.cache else 'bell',
                'player', 'save', 'edit', 'delete', 'choise', 'setting',
                'break', 'history', 'logs', 'ok', 'ok', 'down', 'ok',
                'update', 'check', 'load', 'copy', 'right')
        ico = ('animevost', 'mask', 'ranobe')
        [v.setIcon(seticon(icon[i])) for i, v in enumerate(self.tool)]
        for i in (self.combo[0], self.combo[5]):
            [i.setItemIcon(j, seticon(v)) for j, v in enumerate(ico)]

    def trayExecute(self, reason):
        if reason == QSystemTrayIcon.Trigger:
            tuple((i.hide() for i in self.dock))
            self.show() if self.click % 2 == 0 else self.hide()
            self.setGeoApp() if self.click % 2 == 0 and \
                                not self.opened else None
            self.click += 1
            self.opened = 1

    def checkGeometry(self):
        geo = tuple(self.data.get()['geometry'])
        sizing = self.location.getSize()
        index = [i for i, v in enumerate(sizing) if v == geo][0]
        self.combo[4].setCurrentIndex(index)
        self.setGeoApp()

    def setGeoApp(self):
        """ Change the location of the application. """
        data, index = self.data.get(), self.combo[4].currentIndex()
        data['geometry'] = self.location.set(index)
        self.data.set(data)
        self.setGeometry(*data['geometry'])
        self.setGeometryDock()

    def setGeometryDock(self):
        """ Setting up the location of the docks. """
        geo = self.data.get()['geometry']
        size = ((330, 223), (350, 225), (270, 91), (350, 225), (160, 87),
                (191, 61), (328, 473), (172, 61))
        [self.geoDock(i, v, geo, size[i]) for i, v in enumerate(self.dock)]

    def geoDock(self, index, dock, geometry, size):
        dock.activateWindow() if dock.isWindow() else None
        if index == 0:
            dock.setGeometry(geometry[0]+32, geometry[1]+12, *size)
        elif index in (1, 3):
            dock.setGeometry(geometry[0]+22, geometry[1]+10, *size)
        elif index == 2:
            dock.setGeometry(geometry[0]+62, geometry[1]+75, *size)
        elif index == 4:
            dock.setGeometry(geometry[0]+117, geometry[1]+80, *size)
        elif index == 5:
            if self.combo[0].currentIndex() == 0:
                geo = (geometry[0]+101, geometry[1]+93, *size)
            else:
                rez = self.location.get()
                cond = rez[0] - (geometry[0] + geometry[2])
                posx = 10 if cond < 770 else geometry[2]+50
                geo = (posx, 10, 770, rez[1]-20)
            dock.setGeometry(*geo)
            dock.setMinimumSize(*geo[2:])
            dock.setMaximumSize(*geo[2:])
        elif index == 6:
            dock.setGeometry(geometry[0]+35, 225, *size)
        elif index == 7:
            dock.setGeometry(geometry[0]+100, geometry[1]+100, *size)

    def listChangeSheme(self):
        self.combo[3].clear()
        my = f'{environ["HOME"]}/.config/anima/themes'
        files = sorted([f[:-5] for f in listdir(my)
                        if isfile(joinfile(my, f)) and '.json' in f])
        [self.combo[3].addItem(seticon('sheme'), i) for i in files]
        self.combo[3].setCurrentIndex(files.index(self.data.get()['mode']))
        self.changeColorSheme()

    def changeColorSheme(self):
        theme = self.combo[3].currentText()
        getting = DoingWithData(f'themes/{theme}').get()
        colors = dict(zip(range(9), [getting[i] for i in getting]))

        self.setStyleSheet(f'background: {colors[1]}; color: {colors[0]};')
        tuples = (self.combo, (*self.tool, self.ui.checkBox,
                  self.ui.checkBox_2, self.ui.checkBox_3), self.lcd[:2],
                  self.dock, self.box, self.spin, self.line)
        none = (*self.tool[:4], self.tool[8], *self.tool[10:12])
        for i in range(2, 9):
            [j.setStyleSheet(f'background: {colors[i]}') for j in tuples[i-2]]
        [i.setStyleSheet('border: none;') for i in none]
        style = (f'background: {colors[2]};', 'margin: 0;', 
                 f'selection-background-color: {colors[3]};')
        self.combobox.completer.popup().setStyleSheet(' '.join(style))
        data = self.data.get()
        if data['mode'] != theme:
            data['mode'] = theme
            self.data.set(data)
        self.sourceChanged()

    def message(self, txt, ico=False, but=False):
        """ Global function for alert. """
        al = QMessage()
        data = self.data.get()
        geo = data['geometry'][:2:]
        mode = DoingWithData(f'themes/{data["mode"]}').get()['color5']
        al.setIcon(QMessage.Information) if ico else None
        al.setText(txt)
        al.setStyleSheet(f'background: {mode}')
        al.setGeometry(geo[0] + 64, geo[1] + 52, 200, 200)
        al.setStandardButtons(QMessage.Ok | QMessage.Cancel) if but else None
        return al.exec()

    def clickExport(self):
        tab, history = self.combo[5].currentText(), self.data.get()['history']
        format = self.combo[6].currentText()
        self.export.export(tab, format, history)

    def changeHistory(self):
        tab, history = self.combo[5].currentText(), self.data.get()['history']
        self.export.change(self.line[3], tab, history)

    def changeMode(self):
        tab, data = self.combo[0].currentIndex(), self.data.get()
        self.view.showed(data, tab, self.combo[1], seticon)
        self.combo[1].setCurrentIndex(self.local_index[tab])
        self.sourceChanged()
        self.__dockPlay(data, tab)

    def __dockPlay(self, data, tab):
        size = ((191, 61), (770, self.location.get()[1] - 20))[0 if tab == 0
                                                                        else 1]
        self.geoDock(5, self.dock[5], data['geometry'], size)
        self.line[5].hide() if tab == 0 else self.line[5].show()
        self.box[4].hide() if tab == 0 else self.box[4].show()
        self.bar[2].hide() if tab == 0 else self.bar[2].show()
        None if tab == 0 else self.box[4].resize(size[0], size[1]-54)
        self.dock[5].setWindowTitle('Open Series:') if tab == 0 else None

    def showView(self):
        data, index = self.data.get(), self.combo[11].currentIndex()
        mode = (data['anime']['track-name'], *data['manga']['track-name'])
        icon = seticon('mask' if index else 'animevost')
        hint = f'Released today on {self.combo[11].currentText()}'

        self.combo[2].clear()
        self.combo[2].setToolTip(hint)
        [self.combo[2].addItem(icon, i) for i in mode[index]]
        self.combo[2].setCurrentIndex(0)

    def showCheckWebSite(self):
        web = ('AnimeVost', 'ReadManga', 'MintManga', 'Manga-chan',
               'MangaPoisk')
        [self.combo[11].addItem(seticon('mask' if i != 0 else 'animevost'), v)
            for i, v in enumerate(web)]

    def changeLine(self, edit):
        """ Setting default color sheme for all QLineEdit. """
        sleep(1)
        edit.setText('')
        data = self.data.get()['mode']
        mode = DoingWithData(f'themes/{data}').get()['color4']
        edit.setStyleSheet(f'background: {mode}')
        self.dock[2].close()

    def changeIcon(self):
        sleep(1)
        self.defaultIcons()

    def changeBar(self):
        sleep(0.8)
        [i.default() for i in self.funcs]
        self.ledState(False)

    def ledState(self, enable, color=QLed.Red, state=None):
        self.led.onColour = color
        self.led.setToolTip('Not Working..' if not enable else state)
        self.led.value = enable

    def sourceChanged(self):
        tab, data = self.combo[0].currentIndex(), self.data.get()
        ind, mode = self.combo[1].currentIndex(), self.combo[0].currentText()
        self.local_index[tab] = self.local_index[tab] if ind == -1 else ind
        self.mode.changed(mode, self.combo[1], self.lcd, self.ui.toolButton_20,
                          self.tool[5], self.line[1], tab, data,
                          self.ui.toolButton_19)
        self.combobox.lineEdit().setCursorPosition(0)
        if tab != 0 and not self.ui.checkBox_2.isChecked() and \
                            self.dock[5].isWindow():
            if data[mode]['urls'][ind] not in self.box[4].url().toString():
                self.box[4].setUrl(QUrl(data[mode]['urls'][ind]))
            self.dock[5].setWindowTitle(self.combo[1].currentText())

    def sourceEdit(self):
        vars = (self.data.get(), self.combo[0].currentText(),
                self.combo[0].currentIndex(), self.combo[1].currentIndex(),
                self.spin,self.combo[1].currentText())
        if self.repetitionCheckQueue((2, vars)):
            self.queue.append((2, vars))
            self.queue_s = True if self.queue_d else False
            self.edited(vars) if len(self.queue) > 1 else None
        else:
            self.tray.showMessage('Warning!', 'Command is already running...',
                                  seticon('close'), msecs=10000)

        self.dock[2].close()

    def edited(self, var):
        data, self.notify = self.mode.edited(*var)
        self.data.set(data)
        self.queue_change = True

    def sourceSave(self):
        vars = (self.data.get(), self.combo[0].currentText(),
                self.combo[0].currentIndex(), self.spin[:2],
                self.line[0], self.ui.checkBox.isChecked(),
                self.combo[2].currentIndex(), self.combo[11].currentIndex())

        if self.repetitionCheckQueue((1, vars)):
            self.saved(vars) if self.queue else None
            self.queue.append((1, vars))
            self.queue_s = True if self.queue_d else False
        else:
            self.tray.showMessage('Warning!', 'Command is already running...',
                                  seticon('close'), msecs=10000)

    def saved(self, var):
        data = self.mode.saved(*var)
        self.data.set(data)
        self.global_mode = True
        Thread(target=self.changeLine, args=(self.line[0],)).start()

    def sourceClear(self): self.now.cleared(self.spin, self.values)

    def sourceDelete(self):
        msg_delete = self.message('Do you really want to delete this post?',
                                  True, True)

        if msg_delete == QMessage.Ok:
            msg_history = self.message('Save to history?', True, True)
            save = True if msg_history == QMessage.Ok else False
            vars = (self.data.get(), self.combo[0].currentText(),
                    self.combo[0].currentIndex(), self.combo[1].currentIndex(),
                    save)

            if self.repetitionCheckQueue((3, vars)):
                self.queue.append((3, vars))
                self.queue_s = True if self.queue_d else False
                self.combo[1].removeItem(self.combo[1].currentIndex())
            else:
                self.tray.showMessage('Warning!', 'Command is already running...',
                                      seticon('close'), msecs=10000)

    def deleted(self, var):
        data, self.notify = self.mode.deleted(*var)
        self.data.set(data)
        self.global_mode = True

    def sourceSeries(self):
        self.dock[5].opening()
        if self.combo[0].currentText() == 'anime':
            self.view.generateSeries(self.down, self.combo[1], self.combo[9])

    def sourcePlayer(self):
        if self.combo[0].currentText() == 'anime':
            self.view.player(int(self.combo[9].currentText()),
                             self.combo[10].currentText(), self.combo[1],
                             self.down)

    def sourceWeb(self):
        self.view.open(self.data.get(), self.combo[0].currentText(), seticon,
                       self.tool[1], self.combo[1].currentIndex(),
                       self.changeIcon, self.ui.checkBox.isChecked(),
                       self.combo[11].currentIndex())

    def sourceLog(self):
        txt = self.view.loger(self.data.get(), self.combo[0].currentIndex(),
                              self.combo[0].currentText())
        self.line[4].clear()
        self.line[4].addItems(txt.split('\n'))
        self.click_notify = 0
        self.dock[3].opened('Log file:')

    def sourceDownloading(self):
        vars = (self.lcd[0].intValue(), self.combo[1].currentIndex(),
                self.message, self.combo[7].currentIndex(),
                self.combo[8].currentIndex())
        if self.repetitionCheckQueue((5, vars)):
            self.queue.append((5, vars))
            self.queue_s = True if self.queue_d else False
        else:
            self.tray.showMessage('Warning!', 'Command is already running...',
                             seticon('close'), msecs=10000)

    def tracked(self):
        if self.repetitionCheckQueue(0) and not self.queue:
            self.timer[1].stop()
            self.tracking_start = False
            self.queue.append(0)
            self.queue_s = True if self.queue_d else False
        else:
            self.tray.showMessage('Warning!', 'Command is already running...',
                                  seticon('close'), msecs=10000)

    def sourceTrack(self):
        self.error_connect, box = False, self.ui.checkBox_3.isChecked()
        if networkConnected() and not self.enable and box:
            self.ledState(True, QLed.Blue, 'Tracking..')
            self.enable = self.track_list = True
            data, self.tray_set = self.track.run(self.data.get(), self.led)
            self.data.set(data)
            self.tracking_start = True
            self.showView()
            self.enable = False
            self.changeBar()
        elif not networkConnected():
            self.showView()
            self.error_connect = True
        self.track_list = False

    def downloading(self, var):
        self.error_connect = False
        if networkConnected() and not self.enable and \
                                       self.combo[0].currentText() in 'anime':
            self.ledState(True, QLed.Green, 'Downloading..')
            self.enable = True
            data = self.data.get()
            self.tab = 3
            self.load.run(data, var)
            self.enable = False
            self.changeBar()
        elif not networkConnected():
            self.error_connect = True

    def choiseValue(self, flag):
        data, mode = self.data.get(), self.combo[0].currentText()
        tab, index = self.combo[0].currentIndex(), self.combo[1].currentIndex()

        self.dock[2].opened('Editing:' if flag else 'Saving:')
        None if flag else self.line[0].setFocus()
        self.values = self.now.current(data, mode, tab, index, self.spin[:2]) \
                if flag else self.now.default(self.spin[:2])
        self.flag = flag

    def choiseMode(self): self.sourceEdit() if self.flag else self.sourceSave()

    def choiseNotify(self):
        self.dock[3].opened('Notifications:')
        self.line[4].clear()
        data, self.notify, note = self.notification.show(self.data.get())
        self.data.set(data)
        self.click_notify = 1 if isinstance(note, list) else 0
        self.line[4].addItems(note if isinstance(note, list) else [note])

    def checkItems(self, flag):
        if self.repetitionCheckQueue((4, flag)):
            self.queue.append((4, flag))
            self.queue_s = True if self.queue_d else False
        else:
            self.tray.showMessage('Warning!', 'Command is already running...',
                                  seticon('close'), msecs=10000)


    def upCheckItems(self, flag):
        if networkConnected() and not self.enable:
            color, state = QLed.Orange, 'Checking'
            if flag:
                color, state = QLed.Purple, 'Updating'

            tool = f'{state} {self.combo[0].currentText()}...'
            self.ledState(True, color, tool)
            tab, data = self.combo[0].currentIndex(), self.data.get()
            self.enable, self.suffix, self.tab = True, False, tab
            data, self.tray_set = self.funcs[tab].run(data, flag)
            self.data.set(data)
            self.enable, self.suffix = False, True
            self.changeBar()
        elif not networkConnected():
            self.error_connect = True

    def editLoadPercent(self):
        self.notify = self.choiseNotifyValue(self.notify)
        cache = (self.load.chan, self.funcs[self.tab].getPercent(),
                 self.load.getDownload(), self.suffix, self.enable,
                 *self.cached.getValue(self.tab if self.tab < 3 and self.enable
                                            else self.combo[0].currentIndex(),
                                       self.enable, self.load.downloading,
                                       self.notify, self.track_list,
                                       self.bar[1]),
                 self.manga.getFormat(), self.spin[2].time().toString('mm'))

        if self.global_mode:
            self.golbal_mode = False
            self.changeMode()

        if self.queue_change:
            self.queue_change = False
            self.sourceChanged()

        if self.tracking_start:
            self.tracking_start = False
            self.setNewRange()

        if self.queue_s:
            self.queue_s = False
            Thread(target=self.queueNow).start()

        if self.error_connect:
            self.error_connect = False
            self.tray.showMessage('Error!!!', 'No internet connection...',
                             seticon('close'), msecs=10000)

        if not self.cache:
            self.cache = cache
        elif self.cache != cache:
            index = [i for i in range(len(cache)) if self.cache[i] != cache[i]]
            for i in index:
                if i == 0: self.cashing[0](self.load.chan, self.update_index)
                elif i in (1, 2): self.cashing[i](cache[i])
                elif i in (3, 4): self.__restoreShowIndex(*cache[3:5][::-1])
                elif i == 5: self.cashing[i](seticon(cache[i]))
                elif i in (6, 7): self.__trayUpdate(*cache[6:8])
                elif i == 8: self.bar[0].setFormat(cache[i])

            self.cache = cache

    def __trayUpdate(self, ico, tool):
        self.tray.setIcon(seticon(ico))
        self.tray.setToolTip(tool)

    def __restoreShowIndex(self, enable, suffix):
        if not enable and suffix:
            index, self.suffix = self.combo[1].currentIndex(), False
            self.changeMode()
            self.combo[1].setCurrentIndex(index)
            self.sourceChanged()

    def stoped(self):
        """ Forced ending work of functions. """
        if self.chrome().read():
            self.dock[7].opened('Kill you really want to leave')
            self.kill_flag = True
        else:
            proc = ("Kill processes:", 'No active process for ending!')
            self.tray.showMessage(*proc, seticon('close'), msecs=5000)

    def dockStop(self):
        if self.kill_flag:
            kill = 'killall -s 9 chromedriver'
            [i.breaking() for i in (*self.funcs, self.load)]
            system(kill)
            self.dock[7].close()
        else:
            self.dock[7].close()
            self.kill_flag = True
            self.dockStop() if self.enable else None
            path = f'{environ["HOME"]}/.cache/anima'
            self.cached.write(path, self.cache) if self.cache else None
            self.close()

    def closed(self):
        """Shutdown of application. """
        self.dock[7].opened('Do you really want to leave?')
        self.kill_flag = False

    def loadUrl(self):
        url = self.line[5].text()
        request = QUrl(self.line[5].text()) if check_url(url) else \
            QUrl(f'https://www.google.com/search?q={"+".join(url.split())}')
        self.box[4].setUrl(request)

    def copyCurrentLink(self):
        copy(self.box[4].url().toString())
        self.tool[19].setIcon(seticon('completed'))
        self.changeIcon()

    def setWebUrl(self):
        self.changeZoom(self.bar[3].value())
        self.line[5].setText(self.box[4].url().toString())

    def changeProgress(self, value):
        tab = self.combo[0].currentIndex()
        self.bar[2].hide() if value == 100 and tab != 0 else self.bar[2].show()

    def choiseNotifyValue(self, notify):
        tray, self.tray_set = self.tray_set, ''
        if tray and self.dock[3].isVisible():
            data, state = self.data.get(), ('anime', 'manga', 'ranobe')
            note = [data['notify'][i][::-1] for i in state]
            self.line[4].clear()
            self.line[4].addItems(sum(note, []))
            checkVoice(notify, self.tray, *tray)
            return 'checked'
        elif tray:
            return checkVoice(notify, self.tray, *tray)
        else:
            return notify

    def openView(self):
        data, mode = self.data.get(), self.combo[11].currentIndex()
        index = self.combo[2].currentIndex()
        link = (data['anime']['track-link'], *data['manga']['track-link'])

        self.box[4].setUrl(QUrl(link[mode][index]))

    def setNewRange(self):
        self.timer[1].stop()
        self.timer[1].start(int(self.spin[2].time().toString('mm'))*60*1000)

    def openNotify(self, item):
        if self.click_notify:
            text = item.text()
            self.dock[3].close()
            mode = 0 if '[A]' in text else 1 if '[M]' in text else 2
            name = 'names' if mode in (1, 2) else 'name'
            self.combo[0].setCurrentIndex(mode)
            data = self.data.get()[self.combo[0].currentText()][name]
            index = [i for i, v in enumerate(data) if v in text][0]
            self.combo[1].setCurrentIndex(index)
            self.sourceChanged()

    def changeZoom(self, start):
        self.box[4].setZoomFactor(float(f'0.{start}'))
        self.bar[3].setToolTip(f'{start} %')

    def repetitionCheckQueue(self, new):
        if isinstance(new, tuple):
            for i in self.queue:
                if isinstance(i, tuple):
                    if new[1] in i:
                        return False
        return True

    def queueNow(self):
        functions = (self.sourceTrack, self.saved, self.edited,
                     self.deleted, self.upCheckItems, self.downloading)
        if self.queue:
            self.queue_d = False

            if isinstance(self.queue[0], tuple):
                functions[self.queue[0][0]](self.queue[0][1])
            else:
                functions[self.queue[0]]()

            self.queue.pop(0)

            if self.queue: self.queueNow()

        self.queue_d = True
